<template>
  <div>
    <van-nav-bar @click-left="$router.back()" left-arrow title="编辑资料" />
    <!-- 头像区域 -->
    <div class="avatar-box">
      <van-uploader :after-read="afterRead" />
      <van-image fit="cover" round :src="userInfo.photo" />
    </div>
    <!-- 三个cell区域：显示名字、性别、生日 -->
    <van-cell-group>
      <van-cell @click="doEditName" title="名称" :value="userInfo.name" />
      <van-cell
        @click="popShow = true"
        title="性别"
        :value="userInfo.gender ? '男' : '女'"
      />
      <van-cell @click="showBirthday" title="生日" :value="userInfo.birthday" />
    </van-cell-group>
    <!-- 弹出框组件调用 修改姓名-->
    <van-dialog
      @confirm="updateName"
      v-model="nameShow"
      title="修改名字"
      show-cancel-button
    >
      <van-field ref="nameInp" class="name-field" v-model="editName" />
    </van-dialog>

    <!-- 修改性别 -->
    <van-popup class="genderPop" v-model="popShow" position="bottom">
      <van-nav-bar
        @click-left="popShow = false"
        title="修改性别"
        left-text="取消"
      />
      <van-cell @click="changeGender(1)" title="男" is-link />
      <van-cell @click="changeGender(0)" title="女" is-link />
    </van-popup>
    <!-- 修改生日 -->
    <van-popup v-model="birthShow" position="bottom" class="birthPop">
      <van-datetime-picker
        @cancel="birthShow = false"
        @confirm="editBirth"
        v-model="currentDate"
        type="date"
        title="选择年月日"
        :min-date="minDate"
        :max-date="maxDate"
      />
    </van-popup>
    <!-- 图片裁剪容器 -->
    <div class="crop-box" v-if="cropShow">
      <!-- 
        ref： 方便后面通过$refs找到它 
        img： 设置要被裁剪的图片
        autoCrop：代表产生一个裁剪框
        autoCropWidth和autoCropHeight设置裁剪框宽高
      -->
      <vueCropper
        ref="cropper"
        :img="cropImg"
        autoCrop
        autoCropWidth="180"
        autoCropHeight="180"
      ></vueCropper>

      <van-button @click="doCrop" type="primary">裁剪</van-button>
      <van-button @click="cropShow = false" type="primary">取消</van-button>
    </div>
  </div>
</template>

<script>
import { editUserInfoAPI, changeUserPhotoAPI } from "@/api";
import moment from "moment";
import { VueCropper } from "vue-cropper";
export default {
  components: {
    VueCropper,
  },
  data() {
    return {
      nameShow: false,
      editName: "",
      popShow: false,
      birthShow: false,
      minDate: new Date(1949, 10, 1),
      maxDate: new Date(),
      currentDate: new Date(1996, 10, 15),
      cropImg: "",
      cropShow: false,
    };
  },

  methods: {
    doEditName() {
      this.nameShow = !this.nameShow;
      this.editName = this.userInfo.name;
    },
    async updateName() {
      if (this.editName == "") return this.$toast("请输入名字");
      await editUserInfoAPI({ name: this.editName });
      this.$store.commit("changeUserInfo", {
        ...this.userInfo,
        name: this.editName,
      });
    },
    async changeGender(gender) {
      await editUserInfoAPI({ gender });
      this.$store.commit("changeUserInfo", {
        // 我把之前的属性还都得保留下来
        ...this.userInfo,
        gender,
      });
      this.popShow = !this.popShow;
    },
    showBirthday() {
      this.birthShow = !this.birthShow;
      this.currentDate = new Date(this.userInfo.birthday);
    },
    async editBirth() {
      // 发请求修改生日
      // 接口要求传递的是字符串，所以你不能直接传currentDate，因为它是日期对象
      // 所以现在我们要把日期对象，改成字符串形式 - "YYYY-MM-DD"
      const birthday = moment(this.currentDate).format("YYYY-MM-DD");
      await editUserInfoAPI({ birthday });

      // 改动到vuex
      this.$store.commit("changeUserInfo", {
        ...this.userInfo,
        birthday,
      });
      // 隐藏弹出层
      this.birthShow = false;
    },
    afterRead(data) {
      this.cropImg = data.content;
      // 把裁剪容器显示出来
      this.cropShow = !this.cropShow;
    },
    doCrop() {
      this.$refs.cropper.getCropBlob(async (data) => {
        // 这里的参数data就是裁剪后的文件对象
        // 拿到裁剪后的对象是为了上传给服务器
        // 所以这里要发请求
        // ajax不能直接上传文件，要上传文件必须要用到 FormData 这个对象（ajax2.0）
        // 如果jQuery要用 FormData 上传，都还得加两句话contentType:false processData:false

        // axios本质上发的就是ajax请求，所以肯定也得要FormData
        let fm = new FormData();
        fm.append("photo", data);
        // 直接把FormData作为对象参数传递进去即可
        let res = await changeUserPhotoAPI(fm);
        // console.log(res) // res.data.data.photo 就是服务器返回的图片上传后的地址

        // 发完请求要更新vuex里的头像
        this.$store.commit("changeUserInfo", {
          ...this.userInfo,
          photo: res.data.data.photo,
        });

        // 把裁剪区域隐藏了
        this.cropShow = !this.cropShow;
      });
    },
  },

  created() {
    this.$store.dispatch("getUserInfo");
  },

  computed: {
    userInfo() {
      return this.$store.state.userInfo;
    },
  },
};
</script>

<style lang="less" scoped>
.avatar-box {
  @width: 120px;
  height: @width;
  display: flex;
  justify-content: center;
  align-items: center;

  .van-image {
    width: 100px;
    height: 100px;
  }

  .van-uploader {
    // 因为只有当绝对定位或者固定定位才不占位置
    // 就能显示图片
    position: absolute;
    z-index: 999;

    ::v-deep .van-uploader__upload {
      width: 100vw;
      height: @width;
      opacity: 0;
    }
  }
}

.name-field {
  border: 1px solid #ddd;
}

.birthPop {
  height: 240px;
}

.crop-box {
  width: 100vw;
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;

  .van-button {
    position: absolute;
    bottom: 0;

    // 找到最后一个button
    &:last-of-type {
      right: 0;
    }
  }
}
</style>
